﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Linq.Expressions;
using System.Reflection;
using System.Web.Mvc;
using GwLib.JqGridMvc.Extensions;
using System.Data;

namespace GwLib.JqGridMvc
{
    public enum JqGridHeightType
    {
        Pixel = 0,
        Percent100,
        Auto,
        Custom
    }

    public class JqGrid
    {
        private readonly List<JqGridColumn> _columns = new List<JqGridColumn>();
        private readonly JqGridDataSource _dataSource = new JqGridDataSource();
        private readonly JqGridPaging _paging = new JqGridPaging();

        public JqGrid() { }

        public static void Initialize()
        {
            ModelBinders.Binders.Add(typeof(JqGridAjaxEventArgs), new JqGridAjaxEventArgsModelBinder());
        }

        public List<JqGridColumn> Columns
        {
            get { return _columns; }
        }

        public JqGridDataSource DataSource { get { return _dataSource; } }
        public JqGridPaging Paging { get { return _paging; } }
        public string JQuerySelector { get; set; }
        public int? ViewableRowCount { get; set; }
        public int? TotalRowCount { get; set; }
        public int? Width { get; set; }
        public JqGridHeightType HeightType { get; set; }
        public int? Height { get; set; }
        public string CustomHeightTypeExpression { get; set; }
        public string DefaultSortColumnName { get; set; }
        public bool? DefaultSortAscending { get; set; }
        public bool? PerformSearchOnLoad { get; set; }
        //public int viewrecords { get;set; }

        public string LoadCompleteFunction { get; set; }
        public string LoadErrorFunction { get; set; }
        public string GridCompleteFunction { get; set; }
        public string DoubleClickRowFunction { get; set; }

        //TODO: should probably have editing stuff in a different class..
        public string EditUrl { get; set; }
        public bool? IsCellEditingEnabled { get; set; }
        public bool? IsRowSelectionEnabled { get; set; }
        public bool IsDeepCleaningEnabled { get; set; }
        public bool? IsInitialWidthAutomatic { get; set; }
        public bool IsAlternateRowStylingEnabled { get; set; }
        public bool IsForceFitEnabled { get; set; }
        public bool? IsSingleSearchEnabled { get; set; }
        public bool? IsRefreshEnabled { get; set; }
        public bool AutoEncodeHtml { get; set; }
        public bool DeselectAfterSort { get; set; }
        public bool LoadOnlyOnce { get; set; }
        public bool IsHttpPostEnabled { get; set; }
        public string AlternateRowClass { get; set; }
        public string Caption { get; set; }

        public object GenerateResults<T>(IList<T> records, string sidx, string sord, int page, int rows) where T : class
        {
            IList<T> sortedRecords;
            if (sord == "desc") sortedRecords = records.AsQueryable().OrderByDescending(sidx).ToList();
            else sortedRecords = records.AsQueryable().OrderBy(sidx).ToList();
            int pageIndex = Convert.ToInt32(page) - 1;
            int pageSize = rows;
            int totalRecords = records.Count();
            int totalPages = (int)Math.Ceiling((float)totalRecords / (float)pageSize);

            IList<T> pageOfRecords = new List<T>();
            int start = pageIndex * pageSize, j = 0;
            for (int i = start; j < pageSize && i < sortedRecords.Count; i++)
            {
                pageOfRecords.Add(sortedRecords[i]);
                j++;
            }

            dynamic data = new
            {
                total = totalPages,
                page,
                records = totalRecords,
                rows = new object[pageOfRecords.Count]
            };
            
            List<object> dataRecords = new List<object>();
            int m = 0;
            foreach (T record in pageOfRecords)
            {
                dynamic datarow = new
                {
                    i = record.PropertyData(Columns[0].DataSourceFieldName),
                    cell = new object[Columns.Count]
                };
                
                int n = 0;
                foreach (JqGridColumn col in Columns)
                {
                    datarow.cell[n++] = record.PropertyData(col.DataSourceFieldName);
                }

                data.rows[m++] = datarow;
            }

            return data;
        }
                      
        public object GenerateResults<T>(IList<T> records, JqGridAjaxEventArgs args) where T : class
        {
            if (!args.TotalRecordCount.HasValue) 
            {
                args.TotalRecordCount = args.RecordsPerPage;
            }

            int pageIndex = Convert.ToInt32(args.PageNumber) - 1;
            int totalPages = (int)Math.Ceiling((float)args.TotalRecordCount.Value / (float)args.RecordsPerPage);

            dynamic data = new
            {
                total = totalPages,
                page = args.PageNumber,
                records = args.TotalRecordCount.Value,
                rows = new object[records.Count]
            };

            List<object> dataRecords = new List<object>();
            int m = 0;
            foreach (T record in records)
            {
                dynamic datarow = new
                {
                    i = record.PropertyData(Columns[0].DataSourceFieldName),
                    cell = new object[Columns.Count]
                };

                int n = 0;
                foreach (JqGridColumn col in Columns)
                {
                    var obj = record.PropertyData(col.DataSourceFieldName);
                    /*if (obj is DateTime)
                        obj = ((DateTime)obj).ToString("yyyy-MM-dd HH:mm:ss");
                    if (obj is DateTime?)
                    {
                        var ndt = obj as DateTime?;
                        if (ndt.HasValue) obj = ((DateTime?)obj).Value.ToString("yyyy-MM-dd HH:mm:ss");
                        else obj = null;
                    }*/
                    datarow.cell[n++] = obj;
                }

                data.rows[m++] = datarow;
            }

            return data;
        }
    }
}